#include "header/pyramid_rotaryBody.h"

OSG_USING_NAMESPACE


double rotary_height = 3;
double rotary_rings = 30;
double rotary_quads_per_row = 30;


// Rotationsfunktion
float rotaryFunc(float x){
	
	return (2*sin(x) + 4);
}


NodePtr createRotaryBody() {

	
	GeoPTypesPtr rotaryType = GeoPTypesUI8::create();        
	beginEditCP (rotaryType, GeoPTypesUI8::GeoPropDataFieldMask);
	{
		for(int i = 0; i < rotary_rings; i++) {
			rotaryType->addValue(GL_QUADS);
		}
	}
	endEditCP (rotaryType, GeoPTypesUI8::GeoPropDataFieldMask);

	GeoPLengthsPtr rotaryLens = GeoPLengthsUI32::create();    
	beginEditCP (rotaryLens, GeoPLengthsUI32::GeoPropDataFieldMask);
	{
		for(int i = 0; i < rotary_rings; i++) {
			rotaryLens->addValue(rotary_quads_per_row * 4);
		}
	}
	endEditCP (rotaryLens, GeoPLengthsUI32::GeoPropDataFieldMask);
	
	
	
	GeoPositions3fPtr rotaryPnts = GeoPositions3f::create();
	beginEditCP (rotaryPnts, GeoPositions3f::GeoPropDataFieldMask);
	{
		for(float i = 0; i < (2*M_PI); i += (2*M_PI)/rotary_rings) {
			for(float j = 0; j < (2*M_PI)-(2*M_PI)/rotary_quads_per_row; j += (2*M_PI)/rotary_quads_per_row) {
				rotaryPnts->addValue(Pnt3f(rotaryFunc(i) * cos(j), 
				i*rotary_height, 
				rotaryFunc(i) * sin(j)));
			}
		}
	}
	endEditCP (rotaryPnts, GeoPositions3f::GeoPropDataFieldMask);
	
	
	GeoIndicesUI32Ptr rotaryIndices = GeoIndicesUI32::create();
	beginEditCP(rotaryIndices, GeoIndicesUI32::GeoPropDataFieldMask);
	for (int i = 0; i < rotary_rings; i++)
	{
		for (int j = 0; j < rotary_quads_per_row-1; j++) {
			rotaryIndices->addValue(i*rotary_quads_per_row+j);       
			rotaryIndices->addValue((i+1)*rotary_quads_per_row+j);
			rotaryIndices->addValue((i+1)*rotary_quads_per_row+j+1);
			rotaryIndices->addValue(i*rotary_quads_per_row+j+1);
		}
		//close ring
		rotaryIndices->addValue(i*rotary_quads_per_row+rotary_quads_per_row-1);       
		rotaryIndices->addValue((i+1)*rotary_quads_per_row+rotary_quads_per_row-1);
		rotaryIndices->addValue((i+1)*rotary_quads_per_row+0);
		rotaryIndices->addValue(i*rotary_quads_per_row+0);
	}
	endEditCP(rotaryIndices, GeoIndicesUI32::GeoPropDataFieldMask);
	
	
	GeoTexCoords2fPtr rotaryTex = GeoTexCoords2f::create();
	beginEditCP (rotaryTex);
	{
		for(float i = 0; i < (2*M_PI); i += (2*M_PI)/rotary_rings) {
			for(float j = 0; j < (2*M_PI)-(2*M_PI)/rotary_quads_per_row; j += (2*M_PI)/rotary_quads_per_row) {
				rotaryTex->addValue(Vec2f(rotaryFunc(i), i*rotary_height));
			}
		}
	}
	endEditCP (rotaryTex);
	
	
	
	GeoNormals3fPtr rotaryNorms = GeoNormals3f::create();
	beginEditCP(rotaryNorms, GeoNormals3f::GeoPropDataFieldMask);
	{
		float erg[3];
		float norm[3];
		
		float v1[3];
		float v2[3];
		float v3[3];
		float vektor1[3];
		float vektor2[3];
		
		
		
		for(float i = 0; i < (2*M_PI); i += (2*M_PI)/rotary_rings) {
			for(float j = 0; j < (2*M_PI)-(2*M_PI)/rotary_quads_per_row; j += (2*M_PI)/rotary_quads_per_row) {
				
				v1[0] = rotaryFunc(i) * cos(j);
				v1[1] = i*rotary_height;
				v1[2] = rotaryFunc(i) * sin(j);
				
				v2[0] = rotaryFunc(i+(2*M_PI)/rotary_rings) * cos(j);
				v2[1] = (i+(2*M_PI)/rotary_rings)*rotary_height;
				v2[2] = rotaryFunc(i+(2*M_PI)/rotary_rings) * sin(j);
				
				v3[0] = rotaryFunc(i) * cos(j+(2*M_PI)/rotary_quads_per_row);
				v3[1] = i*rotary_height;
				v3[2] = rotaryFunc(i) * sin(j+(2*M_PI)/rotary_quads_per_row);
				
				vektor1[0] = v2[0] - v1[0];
				vektor1[1] = v2[1] - v1[1];
				vektor1[2] = v2[2] - v1[2];
				
				vektor2[0] = v3[0] - v1[0];
				vektor2[1] = v3[1] - v1[1];
				vektor2[2] = v3[2] - v1[2];
				
				
				erg[0] = vektor1[1]*vektor2[2]-vektor1[2]*vektor2[1];
				erg[1] = vektor1[2]*vektor2[0]-vektor1[0]*vektor2[2];
				erg[2] = vektor1[0]*vektor2[1]-vektor1[1]*vektor2[0];
				
				norm[0] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[0];
				norm[1] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[1];
				norm[2] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[2];
				
				rotaryNorms->addValue(Vec3f(norm[0], norm[1], norm[2]));
			}
		}
	}
	endEditCP (rotaryNorms, GeoNormals3f::GeoPropDataFieldMask);
	
	
	
	ImagePtr image = Image::create();
	image->read("materials/ton.jpg");
	
	SimpleTexturedMaterialPtr m1 = SimpleTexturedMaterial::create();	    
	beginEditCP(m1);
	{
		m1->setAmbient      (Color3f(0.3,0.3,0.3));
		m1->setDiffuse      (Color3f(0.8,0.8,0.8));
		m1->setEmission     (Color3f(0.0,0.0,0.0));
		m1->setSpecular     (Color3f(0.3,0.3,0.3));
		m1->setShininess    (20);
		m1->setTransparency (0);
		m1->setColorMaterial(GL_NONE);
		
		m1->setImage        (image);
		m1->setMinFilter    (GL_LINEAR_MIPMAP_LINEAR);
		m1->setMagFilter    (GL_LINEAR);
		m1->setEnvMode      (GL_MODULATE);
	}
	endEditCP (m1);


	GeometryPtr rotaryGeo=Geometry::create();
	beginEditCP (rotaryGeo);
	{
		rotaryGeo->setTypes    (rotaryType);
		rotaryGeo->setLengths  (rotaryLens);
		rotaryGeo->setTexCoords(rotaryTex);
		rotaryGeo->setPositions(rotaryPnts);
		rotaryGeo->setIndices  (rotaryIndices);
		rotaryGeo->setNormals  (rotaryNorms);
		rotaryGeo->setMaterial (m1);
	}
	endEditCP (rotaryGeo);
	
	
	// defines the hole rotaryBody
	NodePtr rotaryBodyNode = Node::create();
	beginEditCP(rotaryBodyNode, Node::CoreFieldMask);
	{
		rotaryBodyNode->setCore(rotaryGeo);
	}
	endEditCP  (rotaryBodyNode, Node::CoreFieldMask);
	
	
/*	NodePtr r1_norm = calcVertexNormalsGeo(rotaryGeo, 5.0);
	SimpleMaterialPtr mat = SimpleMaterial::create();
			    
	GeometryPtr geo = GeometryPtr::dcast(r1_norm->getCore());
	beginEditCP(geo);
		geo->setMaterial(mat);
	endEditCP(geo);
			    
	NodePtr rotaryBody = Node::create();
	beginEditCP(rotaryBody);
		rotaryBody->setCore(Group::create());
		rotaryBody->addChild(r1_norm);
		rotaryBody->addChild(rotaryBodyNode);
	endEditCP(rotaryBody);
	return rotaryBody;*/
	
	
	
	
	
	return rotaryBodyNode;

}
